package com.bskyb.onlinestore.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.acme.serviceavailability.AvailabilityChecker;
import com.acme.serviceavailability.TechnicalFailureException;
import com.bskyb.onlinestore.Basket;
import com.bskyb.onlinestore.InvalidPostCodeException;
import com.bskyb.onlinestore.ThreeDeeAddOnService;

/**
 * This is an implementation class for ThreeDeeAddOnService<br><br>
 * 
 * Four values are required by the service and are input via the corresponding "setters" these are:-<br><br>
 * Add on products - A list of 3D add on products available<br>
 * AvailabilityChecker - Chosen third party AvailabilityChecker<br>
 * Msg 3d in area - A list of String messages to check that indicate the post code has a 3d service <br>
 * Msg post code invalid - A list of String messages to check that indicate the post code is invalid<br>
 * 
 * @author Simon Jenkins
 *
 */

public class ThreeDeeAddOnServiceSDJ implements ThreeDeeAddOnService {

	private String logPref = this.getClass().getName()+": ";
	private Map<String, String> addOnProducts;
	private AvailabilityChecker availabilityChecker;
	private List<String> msgPostCodeInvalid;
	private List<String> msg3dInArea;
	
	public void setMsgPostCodeInvalid(List<String> msgPostCodeInvalid) {
		this.msgPostCodeInvalid = msgPostCodeInvalid;
	}

	public void setMsg3dInArea(List<String> msg3dInArea) {
		this.msg3dInArea = msg3dInArea;
	}

	private List<String> findAddOn3dProducts(Basket basket, String checkMsg) {
		
		List<String> addOns = null;
		if (msg3dInArea.contains(checkMsg)) {	
			for (String key : basket.getProducts()) {
				log("has found: "+key);			
				String addOn = addOnProducts.get(key);
				if (addOn != null) {
					if (addOns == null) {
						addOns = new ArrayList<String>();			
					}
					if ( ! addOns.contains(addOn)) {
						log("returning: "+addOn);
						addOns.add(addOn);
					}
				}
			}
		}	
		return addOns;
	}

	public void setAddOnProducts(Map<String, String> prods) {
		addOnProducts = prods;		
	}
	
	public void setAvailabilityChecker(AvailabilityChecker service) {
		availabilityChecker = service;
	}
	private void log(String msg) {
		System.out.println(logPref+msg);		
	}

	public List<String> checkFor3DAddOnProducts(Basket basket, String postCode)
			throws InvalidPostCodeException {
		log(" --- INVOKED ---");
		String checkMsg = null;
		List<String> prods3d = null;
		try {
			if(postCode == null) {
				log("No postcode, checker bypassed");
			}
			else {
				checkMsg = availabilityChecker.isPostCodeIn3DTVServiceArea(postCode);
			}
			if ( msgPostCodeInvalid.contains(checkMsg) ) {
				log("Invalid postcode detected");
				log(" --- COMPLETE ---");
				throw new InvalidPostCodeException(postCode);
			}
		}
		catch (TechnicalFailureException e) {
			// checkMsg will be null;
			log("AvailabilityChecker Failed");
		}
		if (checkMsg != null) {
			prods3d = findAddOn3dProducts(basket, checkMsg);
		}
		log(" --- COMPLETE ---");	
		return prods3d;
	}
	
}
